package com.free4inno.knowledgems.controller;

import com.free4inno.knowledgems.constants.GroupConstants;
import com.free4inno.knowledgems.constants.ManageConstants;
import com.free4inno.knowledgems.dao.*;
import com.free4inno.knowledgems.domain.ResourceES;
import com.free4inno.knowledgems.domain.SystemManage;
import com.free4inno.knowledgems.service.ResourceEsService;
import com.free4inno.knowledgems.service.UserService;
import com.free4inno.knowledgems.constants.UserConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Author HUYUZHU.
 * Date 2021/1/16 20:37.
 */

@Slf4j
@Controller
@RequestMapping("manage")
public class ManagementController {

    @Autowired
    private UserDAO userdao;

    @Autowired
    private GroupInfoDAO groupInfoDao;

    @Autowired
    private LabelInfoDAO labelInfoDao;

    @Autowired
    private SystemManageDAO systemManageDao;

    @Autowired
    private ResourceEsService esService;

    @Autowired
    private UserService userService;

    @Value("${es.index.resource.name}")
    private String esIndexName;

    @GetMapping("")
    public String management(Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"打开管理页面"+"----"+session.getAttribute(UserConstants.USER_ID));
        if (session.getAttribute(GroupConstants.ROLE_ID).equals(1) || session.getAttribute(GroupConstants.ROLE_ID).equals(2) ||
                session.getAttribute(GroupConstants.ROLE_ID).equals(3) || session.getAttribute(GroupConstants.ROLE_ID).equals(4)) {
            int userNum = userdao.findAll().size();
            int groupNum = groupInfoDao.findAll().size();
            int labelNum1 = labelInfoDao.findByUplevelId(0).size();
            int labelNum2 = labelInfoDao.findAll().size() - labelNum1;
            param.put(ManageConstants.USER_NUM, userNum);
            param.put(ManageConstants.GROUP_NUM, groupNum);
            param.put(ManageConstants.LABEL_NUM1, labelNum1);
            param.put(ManageConstants.LABEL_NUM2, labelNum2);
            log.info(this.getClass().getName()+"----out----"+"当前具有管理权限，返回管理页面"+"----"+session.getAttribute(UserConstants.USER_ID));
            return "manage/manage";
        } else {
            log.info(this.getClass().getName()+"----out----"+"当前用户没有权限，重定向到首页"+"----"+session.getAttribute(UserConstants.USER_ID));
            return "redirect:/";
        }
    }

    @GetMapping("/systemManage")
    public String systemManagement(Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"打开系统管理页面(systemManage)"+"----"+session.getAttribute(UserConstants.USER_ID));

        param.put(ManageConstants.ES_ADDR, systemManageDao.findAllByVariable(ManageConstants.ES_ADDR).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.ES_PERIOD, systemManageDao.findAllByVariable(ManageConstants.ES_PERIOD).orElse(new SystemManage()).getValue());
//         param.put(ManageConstants.TIKA_ADDR, systemManageDao.findAllByVariable(ManageConstants.TIKA_ADDR).orElse(new SystemManage()).getValue());
//         param.put(ManageConstants.TIKA_PERIOD, systemManageDao.findAllByVariable(ManageConstants.TIKA_PERIOD).orElse(new SystemManage()).getValue());
//         param.put(ManageConstants.TIKA_RETRY, systemManageDao.findAllByVariable(ManageConstants.TIKA_RETRY).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.NFS_ADDR, systemManageDao.findAllByVariable(ManageConstants.NFS_ADDR).orElse(new SystemManage()).getValue());
//         param.put(ManageConstants.NFS_TOTAL, systemManageDao.findAllByVariable(ManageConstants.NFS_TOTAL).orElse(new SystemManage()).getValue());
//         param.put(ManageConstants.NFS_INCREMENT, systemManageDao.findAllByVariable(ManageConstants.NFS_INCREMENT).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.MYSQL_ADDR, systemManageDao.findAllByVariable(ManageConstants.MYSQL_ADDR).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.BOOK_LABEL, systemManageDao.findAllByVariable(ManageConstants.BOOK_LABEL).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.APPKEY_PUBLIC, systemManageDao.findAllByVariable(ManageConstants.APPKEY_PUBLIC).orElse(new SystemManage()).getValue());
        param.put(ManageConstants.DEFAULT_PASSWORD, systemManageDao.findAllByVariable(ManageConstants.DEFAULT_PASSWORD).orElse(new SystemManage()).getValue());

        log.info(this.getClass().getName()+"----out----"+"返回系统管理页面"+"----"+session.getAttribute(UserConstants.USER_ID));
        return "manage/systemManage";
    }

    @ResponseBody
    @PostMapping("/setEsConfig")
    public Map<String, Object> setEsConfig(@RequestParam String addr,
                                       @RequestParam String period, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改ES配置(setEsConfig)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (addr.isEmpty() || period.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能含有空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set addr
        systemManage.setVariable(ManageConstants.ES_ADDR);
        systemManage.setValue(addr);
        systemManageDao.save(systemManage);

        // set period
        systemManage.setVariable(ManageConstants.ES_PERIOD);
        systemManage.setValue(period);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/setTikaConfig")
    public Map<String, Object> setTikaConfig(@RequestParam String addr,
                                       @RequestParam String period,
                                       @RequestParam String retry, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改Tika配置(setTikaConfig)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (addr.isEmpty() || period.isEmpty() || retry.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能含有空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set addr
        systemManage.setVariable(ManageConstants.TIKA_ADDR);
        systemManage.setValue(addr);
        systemManageDao.save(systemManage);

        // set period
        systemManage.setVariable(ManageConstants.TIKA_PERIOD);
        systemManage.setValue(period);
        systemManageDao.save(systemManage);

        // set retry
        systemManage.setVariable(ManageConstants.TIKA_RETRY);
        systemManage.setValue(retry);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/setNfsConfig")
    public Map<String, Object> setNfsConfig(@RequestParam String addr, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改Nfs配置(setNfsConfig)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (addr.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能含有空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set addr
        systemManage.setVariable(ManageConstants.NFS_ADDR);
        systemManage.setValue(addr);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/setBookConfig")
    public Map<String, Object> setBookConfig(@RequestParam String id, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改book配置(setBookConfig)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (id.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能为空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // a number?
        try {
            Integer.parseInt(id);
        } catch(Exception e){
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不合法！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，必须为数字"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set labelId
        systemManage.setVariable(ManageConstants.BOOK_LABEL);
        systemManage.setValue(id);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/setAppKeyPublic")
    public Map<String, Object> setAppKeyPublic(@RequestParam String appKey, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改公开appKey(setAppKeyPublic)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (appKey.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能为空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set labelId
        systemManage.setVariable(ManageConstants.APPKEY_PUBLIC);
        systemManage.setValue(appKey);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/setDefaultPassword")
    public Map<String, Object> setDefaultPassword(@RequestParam String password, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"修改默认密码(setDefaultPassword)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();
        SystemManage systemManage = new SystemManage();

        // isNull?
        if (password.isEmpty()) {
            jsonObject.put("code", 500);
            jsonObject.put("msg", "输入不能为空！");
            log.info(this.getClass().getName()+"----out----"+"修改失败，不能为空值"+"----"+session.getAttribute(UserConstants.USER_ID));
            return jsonObject;
        }

        // set setTime
        systemManage.setSetTime(new Timestamp(new Date().getTime()));

        // set default_password
        systemManage.setVariable(ManageConstants.DEFAULT_PASSWORD);
        systemManage.setValue(password);
        systemManageDao.save(systemManage);

        jsonObject.put("code", 200);
        jsonObject.put("msg", "OK");

        log.info(this.getClass().getName()+"----out----"+"修改成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @GetMapping("/mysqlStatus")
    public Map<String, Object> mysqlStatus(HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"获取mysql状态(mysqlStatus)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();

        long startTime = System.currentTimeMillis();
        SystemManage systemManage = systemManageDao.findAllByVariable("kms_version").orElse(new SystemManage());
        long endTime = System.currentTimeMillis();

        jsonObject.put(ManageConstants.KMS_VERSION, systemManage.getValue());
        jsonObject.put(ManageConstants.TIME_DELAY, (endTime - startTime) + "ms");

        log.info(this.getClass().getName()+"----out----"+"返回mysql状态"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @GetMapping("/esDelay")
    public Map<String, Object> esDelay(@RequestParam String query, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"检测es时延(esDelay)"+"----"+session.getAttribute(UserConstants.USER_ID));

        Map<String, Object> jsonObject = new HashMap<>();

        long startTime = System.currentTimeMillis();
        Page<ResourceES> resourceESPage = esService.searchResourceES(1, 10, query, null, null, 1, true,session.getAttribute(UserConstants.USER_ID).toString());
        long endTime = System.currentTimeMillis();

        jsonObject.put(ManageConstants.QUERY, query);
        jsonObject.put(ManageConstants.TIME_DELAY, (endTime - startTime) + "ms");
        jsonObject.put(ManageConstants.RESULT, "success");

        log.info(this.getClass().getName()+"----out----"+"返回es时延检测结果"+"----"+session.getAttribute(UserConstants.USER_ID));

        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/esClone")
    public Map<String, Object> esClone(@RequestParam String name, @RequestParam String appKey, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"备份索引（cloneIndex）"+"----"+session.getAttribute(UserConstants.USER_ID));
        Map<String, Object> jsonObject = new HashMap<>();
        String msg = "";
        /* 用户鉴权 */
        String userId = session.getAttribute(UserConstants.USER_ID).toString();
        if (userService.isSuperUser(userId) && checkAppKey(appKey)) {
            /* 执行备份操作 */
            if (esService.cloneIndex(esIndexName, name)) {
                msg = ManageConstants.OK;
                log.info(this.getClass().getName()+"----out----"+"备份成功"+"----"+session.getAttribute(UserConstants.USER_ID));
            } else {
                msg = ManageConstants.ERROR_BACKUP;
                log.info(this.getClass().getName()+"----out----"+"备份失败"+"----"+session.getAttribute(UserConstants.USER_ID));
            }
        } else {
            msg = ManageConstants.NO_PERMISSION;
            log.info(this.getClass().getName()+"----out----"+"用户没有权限"+"----"+session.getAttribute(UserConstants.USER_ID));
        }
        jsonObject.put("msg", msg);
        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/esRebuild")
    public Map<String, Object> esRebuild(@RequestParam String appKey, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"重建（esRebuild）"+"----"+session.getAttribute(UserConstants.USER_ID));
        Map<String, Object> jsonObject = new HashMap<>();
        String msg = "";
        /* 用户鉴权 */
        String userId = session.getAttribute(UserConstants.USER_ID).toString();
        if (userService.isSuperUser(userId) && checkAppKey(appKey)) {
            /* 执行重建操作 */
            // 1. 备份索引
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            String timestamp = df.format(new Date());
            String bakIndexName = esIndexName + "_bak_" + timestamp;
            if (esService.cloneIndex(esIndexName, bakIndexName)) {
                // 2. 重建索引
                if (esService.rebuildIndex(esIndexName)){
                    msg = ManageConstants.OK;
                    log.info(this.getClass().getName()+"----out----"+"备份索引成功"+"----"+session.getAttribute(UserConstants.USER_ID));
                } else {
                    msg = ManageConstants.ERROR_REBUILD;
                    log.info(this.getClass().getName()+"----out----"+"重建时错误，重建失败"+"----"+session.getAttribute(UserConstants.USER_ID));
                }
            } else {
                msg = ManageConstants.ABNORMAL;
                log.info(this.getClass().getName()+"----out----"+"备份索引异常，重建失败"+"----"+session.getAttribute(UserConstants.USER_ID));
            }
        } else {
            msg = ManageConstants.NO_PERMISSION;
            log.info(this.getClass().getName()+"----out----"+"用户没有权限"+"----"+session.getAttribute(UserConstants.USER_ID));
        }
        jsonObject.put("msg", msg);
        return jsonObject;
    }

    @ResponseBody
    @PostMapping("/esDelete")
    public Map<String, Object> esDelete(@RequestParam String name, @RequestParam String appKey, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"删除索引（esDelete）"+"----"+session.getAttribute(UserConstants.USER_ID));
        Map<String, Object> jsonObject = new HashMap<>();
        String msg = "";
        /* 用户鉴权 */
        String userId = session.getAttribute(UserConstants.USER_ID).toString();
        if (userService.isSuperUser(userId) && checkAppKey(appKey)) {
            /* 执行删除操作 */
            if (esService.deleteIndex(name)) {
                msg = ManageConstants.OK;
                log.info(this.getClass().getName()+"----out----"+"删除索引成功"+"----"+session.getAttribute(UserConstants.USER_ID));
            } else {
                msg = ManageConstants.ERROR_DELETE;
                log.info(this.getClass().getName()+"----out----"+"删除索引失败"+"----"+session.getAttribute(UserConstants.USER_ID));
            }
        } else {
            msg = ManageConstants.NO_PERMISSION;
            log.info(this.getClass().getName()+"----out----"+"用户没有权限"+"----"+session.getAttribute(UserConstants.USER_ID));
        }
        jsonObject.put("msg", msg);
        return jsonObject;
    }

    /* 鉴权 appKey */
    private boolean checkAppKey(String appKey) {
        /* 暂时直接写死 */
        return appKey.equals(ManageConstants.APPKEY);
    }
}
